#include "ParsedData.h"
#include "util/StringUtils.h"

namespace parser {

// ParserData

ParsedData* ParsedData::addWarning(std::string warningMsg) {
	this->warnings.append(new std::string(warningMsg));
	return this;
}

std::string ParsedData::getNextWarning() {
	std::string* pWarn = this->warnings.removeFirst();
	std::string warn = *pWarn;
	delete pWarn;
	return warn;
}

bool ParsedData::hasWarnings() {
	return !this->warnings.isEmpty();
}

// IntersectionParserData

IntersectionParsedData::IntersectionParsedData() {
	this->setX(0.0);
	this->setY(0.0);
}

IntersectionParsedData::~IntersectionParsedData() {

}

// getters
double IntersectionParsedData::getX() {
	return this->x;
}

double IntersectionParsedData::getY() {
	return this->y;
}

std::string IntersectionParsedData::getId() {
	return this->id;
}

// setters
IntersectionParsedData* IntersectionParsedData::setX(double x) {
	this->x = x;
	return this;
}

IntersectionParsedData* IntersectionParsedData::setY(double y) {
	this->y = y;
	return this;
}

IntersectionParsedData* IntersectionParsedData::setId(std::string id)
		throw (InvalidDataException) {
	if (id != "") {
		this->id = id;
		return this;
	} else {
		throw(InvalidDataException("El id no puede ser vacio."));
	}
}

std::string IntersectionParsedData::toString() {
	return "id: " + this->id + "; x: " + util::doubleToString(this->x)
			+ "; y: " + util::doubleToString(this->y);
}

// RoadParserData

RoadParsedData::RoadParsedData() {
	this->setLength(100.0);
	this->setMaxSpeed(60.0);
}

RoadParsedData::~RoadParsedData() {

}
// getters
std::string RoadParsedData::getId() {
	return this->id;
}

double RoadParsedData::getLength() {
	return this->length;
}

double RoadParsedData::getMaxSpeed() {
	return this->maxSpeed;
}

std::string RoadParsedData::getIdO() {
	return this->idO;
}

std::string RoadParsedData::getIdD() {
	return this->idD;
}

std::string RoadParsedData::getRoadName(){
	return this->roadName;
}

int RoadParsedData::getInitialNumber(){
	return this->initialNumber;
}

int RoadParsedData::getFinalNumber(){
	return this->finalNumber;
}

RoadType RoadParsedData::getRoadType(){
	return this->roadType;
}

// setters
RoadParsedData* RoadParsedData::setId(std::string id)
		throw (InvalidDataException) {
	if (id != "") {
		this->id = id;
		return this;
	} else {
		throw(InvalidDataException("El id no puede ser vacio."));
	}
}

RoadParsedData* RoadParsedData::setLength(double length) {
	this->length = length;
	return this;
}

RoadParsedData* RoadParsedData::setMaxSpeed(double maxSpeed)
		throw (InvalidDataException) {
	if (maxSpeed > 0.0) {
		this->maxSpeed = maxSpeed;
		return this;
	} else {
		throw(InvalidDataException(
				"La velocidad de una arista debe ser mayor a cero."));
	}
}

RoadParsedData* RoadParsedData::setIdO(std::string idO)
		throw (InvalidDataException) {
	if (idO != "") {
		this->idO = idO;
		return this;
	} else {
		throw(InvalidDataException("El id no puede ser vacio."));
	}
}

RoadParsedData* RoadParsedData::setIdD(std::string idD)
		throw (InvalidDataException) {
	if (idD != "") {
		this->idD = idD;
		return this;
	} else {
		throw(InvalidDataException("El id no puede ser vacio."));
	}
}

RoadParsedData* RoadParsedData::setRoadName(std::string roadName)
		throw (InvalidDataException){
	if (roadName != "") {
		this->roadName = roadName;
		return this;
	} else {
		throw(InvalidDataException("El nombre del camino no puede ser vacio."));
	}
}

RoadParsedData* RoadParsedData::setRoadNumbersRange(std::string roadNumberRange)
		throw (InvalidDataException){
	if (roadNumberRange != "") {
		std::string izq, der = "";
		util::splitString(roadNumberRange, '-', izq, der);
		if (izq != "" && der != ""){
			int initialNumber = util::stringToInt(izq);
			int finalNumber = util::stringToInt(der);
			if (initialNumber >= 0 && finalNumber >= 0){
				this->initialNumber = initialNumber;
				this->finalNumber = finalNumber;
				return this;
			}
			else throw(InvalidDataException("Las alturas no pueden tener valores negativos"));
		}
		else throw(InvalidDataException("Las alturas no pueden estar vacias"));
	} else {
		throw(InvalidDataException("La numeracion del camino no puede ser vacia."));
	}
}

RoadParsedData* RoadParsedData::setRoadType(std::string roadType)
		throw (InvalidDataException){
	if (roadType.compare("calle") == 0) {
		this->roadType = Street;
	} else if (roadType.compare("avenida") == 0) {
		this->roadType = Avenue;
	} else if (roadType.compare("autopista") == 0) {
		this->roadType = Highway;
	} else {
		throw(InvalidDataException("El tipo de ruta \"" + roadType
				+ "\" no es valido."));
	}
	return this;
}

std::string RoadParsedData::toString() {
	std::string type;
	switch (this->roadType) {
	case Street:
		type = "Calle";
		break;
	case Avenue:
		type = "Avenida";
		break;
	case Highway:
		type = "Autopista";
		break;
	}
	return "id: " + this->id + "; idO: " + this->idO + "; idD: " + this->idD
			+ "; length: " + util::doubleToString(this->length)
			+ "; maxSpeed: " + util::doubleToString(this->maxSpeed)
			+ "; roadType: " + type + "; roadName: " + this->roadName
			+ "; initialNumber: " + util::intToString(this->initialNumber)
			+ "; finalNumber: " + util::intToString(this->finalNumber)
			+ ".";
}

// MapLocationParsedData

MapLocationParsedData::MapLocationParsedData() {
	this->setType(Unknown);
}

MapLocationParsedData::~MapLocationParsedData() {

}

std::string MapLocationParsedData::getId() {
	return this->id;
}

std::string MapLocationParsedData::getRoadId() {
	return this->roadId;
}

int MapLocationParsedData::getNumber() {
	return this->number;
}

MapLocationType MapLocationParsedData::getType() {
	return this->type;
}

MapLocationParsedData* MapLocationParsedData::setId(std::string id)
		throw (InvalidDataException) {
	if (id != "") {
		this->id = id;
	} else {
		throw(InvalidDataException("El id no puede ser vacio."));
	}
	return this;
}

MapLocationParsedData* MapLocationParsedData::setRoadId(std::string id)
		throw (InvalidDataException) {
	if (id != "") {
		this->roadId = id;
	} else {
		throw(InvalidDataException("El id de camino no puede ser vacio."));
	}
	return this;
}

MapLocationParsedData* MapLocationParsedData::setNumber(int i)
		throw (InvalidDataException) {
	if (i >= 0) {
		this->number = i;
	} else {
		throw(InvalidDataException(
				"El valor de la altura en el camino no puede ser menor que cero."));
	}
	return this;
}

MapLocationParsedData* MapLocationParsedData::setType(std::string type)
		throw (InvalidDataException) {
	if (type.compare("hotel") == 0) {
		this->type = Hotel;
	} else if (type.compare("restaurant") == 0) {
		this->type = Restaurant;
	} else if (type.compare("comisaria") == 0) {
		this->type = PoliceStation;
	} else if (type.compare("escuela") == 0) {
		this->type = School;
	} else if (type.compare("hospital") == 0) {
		this->type = Hospital;
	} else {
		throw(InvalidDataException("El tipo de objeto de mapa \"" + type
				+ "\" no es valido."));
	}
	return this;
}

MapLocationParsedData* MapLocationParsedData::setType(MapLocationType type) {
	this->type = type;
	return this;
}

std::string MapLocationParsedData::toString() {
	std::string type;
	switch (this->type) {
	case Hotel:
		type = "Hotel";
		break;
	case Restaurant:
		type = "Restaurant";
		break;
	case PoliceStation:
		type = "Policetation";
		break;
	case School:
		type = "School";
		break;
	case Hospital:
		type = "Hospital";
		break;
	case Unknown:
		type = "Unknown";
		break;
	}
	return "id: " + this->id + "; roadId: " + this->roadId + "; number: "
			+ util::intToString(this->number) + "; type: " + type;
}

// ConfigEntryParsedData

ConfigEntryParsedData::ConfigEntryParsedData() {
	this->key = "";
	this->value = "";
}

ConfigEntryParsedData::~ConfigEntryParsedData() {

}

std::string ConfigEntryParsedData::getKey() {
	return this->key;
}

std::string ConfigEntryParsedData::getValue() {
	return this->value;
}

ConfigEntryParsedData* ConfigEntryParsedData::setKey(std::string key)
		throw (InvalidDataException) {
	if (key != "") {
		this->key = key;
	} else {
		throw(InvalidDataException("La key no puede ser vacia."));
	}
	return this;
}

ConfigEntryParsedData* ConfigEntryParsedData::setValue(std::string value)
		throw (InvalidDataException) {
	this->value = value;
	return this;
}

std::string ConfigEntryParsedData::toString() {
	return "key: " + this->key + "; value: " + this->value;
}

} // end of namespace
